#include "StdAfx.h"
#include "DoubleDragon2Machine.h"

CDoubleDragon2Machine::CDoubleDragon2Machine():CDoubleDragonMachine()
{

}

CDoubleDragon2Machine::~CDoubleDragon2Machine()
{
}

int CDoubleDragon2Machine::Init()
{
CDoubleDragonMachine::Init();
MainCPU->SetOp(ReadMainCPU);
MainCPU->SetRead(ReadMainCPU);
MainCPU->SetWrite(WriteMainCPU);
SubCPU->SetOp(ReadSubCPU);
SubCPU->SetRead(ReadSubCPU);
SubCPU->SetWrite(WriteSubCPU);
SoundCPU->SetOp(ReadSoundCPU);
SoundCPU->SetRead(ReadSoundCPU);
SoundCPU->SetWrite(WriteSoundCPU);
return(0);
}

u8 CDoubleDragon2Machine::ReadMainCPU(void *user,u32 addr)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;

if(addr >= 0x8000)				//rom read
	return(M->MainROM[addr]);
if(addr >= 0x4000)				//banked rom
	return(M->ROMPtr[addr & 0x3FFF]);
if(addr < 0x3800)					//ram read
	return(M->RAM[addr]);
switch(addr)
	{
	case 0x3800:	return(M->Input1);
	case 0x3801:	return(M->Input2);
	case 0x3802:	return(M->Input3 | (M->Status & 0x18));
	case 0x3803:	return(0x00);//return(M->Dip1);
	case 0x3804:	return(0x00);//return(M->Dip2);
	}
message("unhandled read (main cpu, addr $%04X)\n",addr);
return(0);
}

void CDoubleDragon2Machine::WriteMainCPU(void *user,u32 addr,u8 data)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;

if(addr < 0x3800)					//ram write
	{
	M->RAM[addr] = data;
	if(addr >= 0x1000 && addr < 0x1400)
		M->WritePalette(addr,data);
	return;
	}
switch(addr)
	{
	case 0x3808:
		message("main cpu: bankswitch: $%02X\n",data);
		M->ROMPtr = M->MainROM + 0x10000 + ((data & 0xE0) >> 5) * 0x4000;
		if(data & 0x10)
			M->Status &= ~0x10;
		else if((M->Status & 0x10) == 0)
			M->SubCPU->NMI();
		return;
	case 0x3809:	break;
	case 0x380A:	break;
	case 0x380B:	//nmi acknowledge
		return;
	case 0x380C:	//firq acknowledge
		return;
	case 0x380D:	//irq acknowledge
		return;
	case 0x380E:	//sound irq acknowledge
		return;
	}
message("unhandled write (main cpu, addr $%04X = $%02X)\n",addr,data);
}

u8 CDoubleDragon2Machine::ReadSubCPU(void *user,u32 addr)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;

if(addr >= 0xC000)				//rom read
	return(M->SubROM[addr]);
if(addr < 0x1000)					//ram/internal register read
	{
	if(addr >= 0x20)
		return(M->SubRAM[addr]);
	//internal register read
	}
if((addr & 0xF000) == 0x8000)	//sprite ram read
	{
	//message("sub cpu: sprite ram read $%04X\n",addr);
	//MAME Double Dragon crash fix
	//if(addr == 0x8049 && M->SubCPU->PC() == 0x6261 && MSPRRAM[addr & 0xFFF] == 0x1f)
	//	return(0x1);
	return(MSPRRAM[addr & 0xFFF]);
	}
message("unhandled read (sub cpu, addr $%04X)\n",addr);
return(0);
}

void CDoubleDragon2Machine::WriteSubCPU(void *user,u32 addr,u8 data)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;

if(addr < 0x1000)					//ram/internal register write
	{
	if(addr >= 0x20)
		{
		M->SubRAM[addr] = data;
		return;
		}
	if(addr == 0x17)
		{
		if(data & 3)
			{
			M->MainCPU->IRQ();
			return;
			}
		}
	}
if((addr & 0xF000) == 0x8000)	//sprite ram write
	{
	addr &= 0xFFF;
	if(addr == 0)
		M->Status |= 0x10;
	MSPRRAM[addr] = data;
	return;
	}
message("unhandled write (sub cpu, addr $%04X = $%02X)\n",addr,data);
}

u8 CDoubleDragon2Machine::ReadSoundCPU(void *user,u32 addr)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;
u32 s;

if(addr >= 0x8000)
	return(M->SoundROM[addr]);
if(addr < 0x1000)
	return(M->SoundRAM[addr]);
switch(addr)
	{
	case 0x1000:
		message("sound latch read\n");
		return(M->SoundLatch);
	case 0x1800:		//adpcm status
		return(M->IdleADPCM[0] | (M->IdleADPCM[1] << 1));
	case 0x2800:		//ym2151 status port 0
		s = (u32)YM2151ReadStatus(M->ym2151);
		return((u8)(s >> 8));
	case 0x2801:
		s = (u32)YM2151ReadStatus(M->ym2151);
		return((u8)(s >> 0));
	}
message("unhandled read (sound cpu, addr $%04X)\n",addr);
return(0);
}

void CDoubleDragon2Machine::WriteSoundCPU(void *user,u32 addr,u8 data)
{
CDoubleDragon2Machine *M = (CDoubleDragon2Machine*)user;
u32 s;

if(addr < 0x1000)
	{
	M->SoundRAM[addr] = data;
	return;
	}
switch(addr)
	{
	case 0x2800:		//ym2151 register port 0
		M->YM2151Register = data;
		return;
	case 0x2801:		//ym2151 data port 0
		YM2151WriteReg(M->ym2151,M->YM2151Register,data);
		return;
	case 0x3800:
	case 0x3801:
	case 0x3802:
	case 0x3803:
	case 0x3804:
	case 0x3805:
	case 0x3806:
	case 0x3807:
		s = addr & 1;
		switch((addr >> 1) & 3)
			{
			case 0:
				M->IdleADPCM[s] = 0;
				MSM5205_reset_w(s,0);
				return;
			case 1:
				M->EndADPCM[s] = (data & 0x7F) * 0x200;
				return;
			case 2:
				M->PosADPCM[s] = (data & 0x7F) * 0x200;
				return;
			case 3:
				M->IdleADPCM[s] = 1;
				MSM5205_reset_w(s,1);
				return;
			}
		break;
	}
message("unhandled write (sound cpu, addr $%04X = $%02X)\n",addr,data);
}
